﻿using System;
using System.Collections.Generic;
using PathologicalGames;
using UnityEngine;
using WorldMapBase;
using WorldMapBase.Display;
using WorldMapNew;
using Yoozoo.Managers;
using Yoozoo.Managers.ResourceManagerV2.Runtime;

namespace WorldMap
{
    class RenderInfo
    {
        public Mesh sharedMesh;
        public Material sharedMaterial;
        public Vector3 localPos;
        public int layer;    //所属层级，比如：山为mountain，受光
    }
    
    /// <summary>
    /// 地图上静态物件的对象管理器
    /// </summary>
    public class WorldMapObjectManager
    {
        private const string m_renderObjectPath = "Assets/ResourcesAssets/World/prefabs/RenderObject.prefab";
        private const string m_renderObjectName = "RenderObject";
        private const string m_worldMapObjectPoolName = "WorldMapObj";
        
        private const string m_renderObjectRootPoolName = "RenderObjectRoot";
        private const string m_renderObjectRootName = "RenderObjectRoot";
        private SpawnPool m_spawnPool;
        private Action m_finishAction;
        private static int s_dealResCount = 0;
        private static int s_resMaxCount = 0;

        /// <summary>
        /// 保存资源的渲染信息（Mesh和Material）
        /// </summary>
        Dictionary<int,List<RenderInfo>> m_renderInfoDic = new Dictionary<int, List<RenderInfo>>();

        private ResLoader _resLoader;

        /// <summary>
        /// 初始化
        /// </summary>
        public void Initialize(Action finishAction)
        {
            _resLoader = ResLoader.Alloc();
            m_finishAction = finishAction;

            PreLoadRenderObject();
            PreLoadResRenderInfo();
        }

        /// <summary>
        /// 预加载只挂载了MeshFilter和MeshRender组件的Gameobject
        /// </summary>
        private void PreLoadRenderObject()
        {
            // ResourcesManager.ReadSync(PoolMgr.Root, m_renderObjectPath, (obj,r) =>
            // {
            //     GameObject go = obj as GameObject;
            //     PrefabPool prefabPool = new PrefabPool(go.transform);
            //     //默认初始化个数
            //     prefabPool.preloadAmount = 100;
            //     //是否开启自动清理模式
            //     prefabPool.cullDespawned = true;
            //     //自动清理，但保留几个对象不清理
            //     prefabPool.cullAbove = 1000;
            //     //每过多久执行一遍自动清理，单位秒
            //     prefabPool.cullDelay = 180;
            //     //每次自动清理对象数
            //     prefabPool.cullMaxPerPass = 5;
            //     //如果我们限制了缓存池里面只能有10个Prefab，如果不勾选它，那么你拿第11个的时候就会返回null。如果勾选它在取第11个的时候他会返回给你前10个里最不常用的那个
            //     prefabPool.limitFIFO = false;
            //
            //     m_spawnPool.CreatePrefabPool(prefabPool);
            // },false);

            //创建空的实例对象缓存池，便于挂载RenderObject
            GameObject goRenderObjectRoot = new GameObject(m_renderObjectRootName);
            PrefabPool renderObjectRootPool = new PrefabPool(goRenderObjectRoot.transform);
            //默认初始化个数
            renderObjectRootPool.preloadAmount = 100;
            //是否开启自动清理模式
            renderObjectRootPool.cullDespawned = true;
            //自动清理，但保留几个对象不清理
            renderObjectRootPool.cullAbove = 1000;
            //每过多久执行一遍自动清理，单位秒
            renderObjectRootPool.cullDelay = 180;
            //每次自动清理对象数
            renderObjectRootPool.cullMaxPerPass = 5;
            //如果我们限制了缓存池里面只能有10个Prefab，如果不勾选它，那么你拿第11个的时候就会返回null。如果勾选它在取第11个的时候他会返回给你前10个里最不常用的那个
            renderObjectRootPool.limitFIFO = false;

            PoolMgr.CreatePool(m_renderObjectRootPoolName, goRenderObjectRoot.transform, (transform =>
            { }), renderObjectRootPool);

            _resLoader.Add2Load(m_renderObjectPath,
                        (success, name, asset) =>
                        {
                            GameObject go = UnityEngine.Object.Instantiate((UnityEngine.Object)asset) as GameObject;
                            PrefabPool prefabPool = new PrefabPool(go.transform);
                            //默认初始化个数
                            prefabPool.preloadAmount = 100;
                            //是否开启自动清理模式
                            prefabPool.cullDespawned = true;
                            //自动清理，但保留几个对象不清理
                            prefabPool.cullAbove = 1000;
                            //每过多久执行一遍自动清理，单位秒
                            prefabPool.cullDelay = 180;
                            //每次自动清理对象数
                            prefabPool.cullMaxPerPass = 5;
                            //如果我们限制了缓存池里面只能有10个Prefab，如果不勾选它，那么你拿第11个的时候就会返回null。如果勾选它在取第11个的时候他会返回给你前10个里最不常用的那个
                            prefabPool.limitFIFO = false;

                            SpawnPool pool = PoolMgr.CreatePool(m_worldMapObjectPoolName, go.transform, (transform =>
                            {
                                //初始化回池属性
                                // transform.localPosition = Vector3.zero;
                                // transform.localRotation = Quaternion.identity;
                            }), prefabPool);
                        }).Load();
        }
        
        /// <summary>
        /// 预加载资源的渲染信息
        /// </summary>
        private void PreLoadResRenderInfo()
        {
            Dictionary<int, ResourceData> resourceDataMap = WorldMapConfigData.ResourceDatas;
            s_resMaxCount = resourceDataMap.Keys.Count;
            foreach (var resourceData in resourceDataMap.Values)
            {
                _resLoader.Add2Load(resourceData.resPath,
                        (success, name, asset) =>
                        {
                            s_dealResCount++;
                            GameObject go = UnityEngine.Object.Instantiate((UnityEngine.Object)asset) as GameObject;
                            if (!m_renderInfoDic.ContainsKey(resourceData.resID))
                            {
                                m_renderInfoDic.Add(resourceData.resID, new List<RenderInfo>());
                            }
                            else
                            {
                                m_renderInfoDic[resourceData.resID].Clear();
                            }

                            var meshRenderer = go.GetComponentsInChildren<MeshRenderer>();

                            for (int i = 0; i < meshRenderer.Length; i++)
                            {
                                var info = new RenderInfo();
                                info.sharedMaterial = meshRenderer[i].sharedMaterial;
                                info.sharedMesh = meshRenderer[i].GetComponent<MeshFilter>().sharedMesh;
                                info.localPos = meshRenderer[i].transform.localPosition;
                                info.layer = meshRenderer[i].gameObject.layer;
                                m_renderInfoDic[resourceData.resID].Add(info);
                            }
                            CheckFinish();
                        }).Load();
            }
        }

        private void CheckFinish()
        {
            if (s_dealResCount == s_resMaxCount)
            {
                if (m_finishAction != null)
                {
                    m_finishAction();
                    m_finishAction = null;
                }
            }
        }

        /// <summary>
        /// 获取对象，遍历RenderInfo字典，找到ResID对应的RenderInfo进行组装
        /// </summary>
        /// <returns></returns>
        public MeshReplaceElement GetMeshReplaceElement(int resID)
        {
            if (!m_renderInfoDic.ContainsKey(resID))
            {
                return null;
            }

            MeshReplaceElement obj = ClassManager.Get<MeshReplaceElement>();
            var renderInfoList = m_renderInfoDic[resID];
            if (renderInfoList.Count > 1)//物件有子结点的情况
            {
                Transform goRoot = PoolMgr.GetPrefab(m_renderObjectRootPoolName, m_renderObjectRootName);
                goRoot.transform.localScale = Vector3.one;
                foreach (var renderInfo in renderInfoList)
                {
                    Transform renderObject = PoolMgr.GetPrefab(m_worldMapObjectPoolName, m_renderObjectName);
            
                    renderObject.GetComponent<MeshFilter>().sharedMesh = renderInfo.sharedMesh;
                    renderObject.GetComponent<MeshRenderer>().sharedMaterial = renderInfo.sharedMaterial;
                    renderObject.transform.localPosition = renderInfo.localPos;
                    renderObject.gameObject.layer = renderInfo.layer;
                    renderObject.SetParent(goRoot);
                }
                
                obj.OnCreate(resID, goRoot.transform);
            }
            else
            {
                Transform renderObject = PoolMgr.GetPrefab(m_worldMapObjectPoolName, m_renderObjectName);
            
                renderObject.GetComponent<MeshFilter>().sharedMesh = renderInfoList[0].sharedMesh;
                renderObject.GetComponent<MeshRenderer>().sharedMaterial = renderInfoList[0].sharedMaterial;
                renderObject.transform.localPosition = renderInfoList[0].localPos;
                renderObject.gameObject.layer = renderInfoList[0].layer;
                
                obj.OnCreate(resID, renderObject);
            }
        
            return obj;
        }

        /// <summary>
        /// 回收对像
        /// </summary>
        public void RecoverItem(MeshReplaceElement element)
        {
            if (element == null)
            {
                return;
            }
        
            if (element.GetRefTrans != null)
            {
                if (element.GetRefTrans.childCount > 0)
                {
                    for (int i = 0; i < element.GetRefTrans.childCount; i++)
                    {
                        PoolMgr.RemovePrefab(m_worldMapObjectPoolName, element.GetRefTrans.GetChild(i));
                    }
                    // Debug.Log("####### " + element.GetRefTrans.gameObject);
                    // GameObject.Destroy(element.GetRefTrans.gameObject);
                    PoolMgr.RemovePrefab(m_renderObjectRootPoolName, element.GetRefTrans);
                }
                else
                {
                    PoolMgr.RemovePrefab(m_worldMapObjectPoolName, element.GetRefTrans);
                }
            }
        }
    }
}